#include "StdAfx.h"
#include "simple_unit_test.h"
#include <list>
#include <string>
#include <iostream>

namespace
{
	class UnitTestManager
	{
	public:
		UnitTestManager()
		{
		}

		static UnitTestManager & instance()
		{
			static UnitTestManager s_instance;
			return s_instance;
		}

		void add_test(const char * funName, std::function<void ()> fn)
		{
			Entry entry;
			entry.m_name = funName;
			entry.m_fn = fn;

			m_entryList.push_back(entry);
		}

		bool run_all_tests()
		{
			bool rst = true;
			for( auto it=m_entryList.begin(); it!=m_entryList.end(); ++it )
			{
				if( !it->run() )
				{
					rst = false;
				}
			}

			return rst;
		}

	private:
		struct Entry
		{
			std::string m_name;
			std::function<void ()> m_fn;

			bool run()
			{
				std::cout << "[" << m_name << "] .... " << std::flush;

				HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
				try
				{
					m_fn();
					
					SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN);
					std::cout << "[OK]" << std::endl;
					::SetConsoleTextAttribute(hConsole, FOREGROUND_INTENSITY);
					return true;
				}
				catch(test::detail::TestException & e)
				{
					SetConsoleTextAttribute(hConsole, FOREGROUND_RED);
					std::cout << "[FAIL]" << std::endl;

					std::cout << e.what() << std::endl;
					::SetConsoleTextAttribute(hConsole, FOREGROUND_INTENSITY);
					return false;
				}
			}
		};

		std::list<Entry> m_entryList;

	private:
		void setConsoleColor()
		{
			HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
			SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN);
		}
	};
}

namespace test
{

	namespace detail
	{
		TestInitializer::TestInitializer(const char * funName, std::function<void ()> fn)
		{
			UnitTestManager::instance().add_test(funName, fn);
		}
	}

	bool run_all_tests()
	{
		return UnitTestManager::instance().run_all_tests();
	}
}
